﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Sunboxsoft.WinForm;
using Sunboxsoft.WinForm.Shell.Components;
using DevExpress.XtraEditors;
using DevExpress.XtraBars;
using System.Drawing;

namespace Sunboxsoft.WinForm.Shell
{

    public class ViewManager : IViewManager
    {
        private const int ActionButtonHeight = 30;
        private const int ActionButtonImageWidth = 40;
        private const int ActionButtonNoImageWidth = 10;
        private const int ActionButtonMaxWidth = 200;

        private MainForm _form;
        private MainContent _ctlViewContainer;
        private LabelControl _ctlTitle;
        private Graphics _mGraphics;

        public ViewManager(MainForm form, LabelControl ctlTitle, MainContent ctlViewContainer)
        {
            _form = form;
            _ctlTitle = ctlTitle;
            _ctlViewContainer = ctlViewContainer;

            _mGraphics = Graphics.FromHwnd(_form.Handle);
        }

        private void SetTitle(IView view)
        {
            _form.ShowDebugText(view.GetType().FullName);

            _ctlTitle.Text = view.GetHeader().Title;
        }

        private void SetTitle(PopupForm form, IView view, string argsTitle)
        {
            if (string.IsNullOrEmpty(argsTitle))
            {
                form.Text = view.GetHeader().Title;
            }
            else
            {
                form.Text = argsTitle;
            }
        }

        /// <summary>
        /// 退出系统
        /// </summary>
        public void Exit()
        {
            _form.Close();
        }

        public void ReplaceRootView(IView view)
        {
            SetTitle(view);

            _ctlViewContainer.RemoveAllView();
            ((Control)view).Dock = DockStyle.Fill;
            _ctlViewContainer.AddView((Control)view);

            for (int index = 0; index < UIContext.Current.ViewContext.Stack.Count; index++)
            {
                // 删除view关联的validation
                ValidationManager.Remove(UIContext.Current.ViewContext.Stack.GetAt(index).View as IView);
            }
            UIContext.Current.ViewContext.Stack.Clear();
            UIContext.Current.ViewContext.Stack.Push(new ViewStackNode(view, ViewDisplayMode.Inner, null, _form, null));

            ActionNodeCollection actions = UIContext.Current.ViewContext.CreateActionCollection(view);
            view.RegisterAction(actions);
            Utils.ToolbarUtil.ApplyToToolbar(_ctlViewContainer.GetToolbar(), actions);

            view.Active(null);
        }

        public void ReplaceView(IView view)
        {
            ViewStackNode currentNode = UIContext.Current.ViewContext.Stack.Pop();
            if (currentNode == null)
            {
                SetTitle(view);

                UIContext.Current.ViewContext.Stack.Push(new ViewStackNode(view, ViewDisplayMode.Inner, null, _form, null));

                ((Control)view).Dock = DockStyle.Fill;
                _ctlViewContainer.AddView((Control)view);

                ActionNodeCollection actions = UIContext.Current.ViewContext.CreateActionCollection(view);
                view.RegisterAction(actions);
                Utils.ToolbarUtil.ApplyToToolbar(_ctlViewContainer.GetToolbar(), actions);

                view.Active(new ViewActiveArgs(""));
            }
            else if(currentNode.DisplayMode == ViewDisplayMode.Inner)
            {
                // 删除当前view关联的validation
                ValidationManager.Remove(currentNode.View as IView);
                SetTitle(view);

                UIContext.Current.ViewContext.Stack.Push(new ViewStackNode(view, ViewDisplayMode.Inner, null, _form, null));

                _ctlViewContainer.RemoveView(currentNode.View);

                ((Control)view).Dock = DockStyle.Fill;
                _ctlViewContainer.AddView((Control)view);

                ActionNodeCollection actions = UIContext.Current.ViewContext.CreateActionCollection(view);
                view.RegisterAction(actions);
                Utils.ToolbarUtil.ApplyToToolbar(_ctlViewContainer.GetToolbar(), actions);

                view.Active(new ViewActiveArgs(""));
            }
            else
            {
                // 删除当前view关联的validation
                ValidationManager.Remove(currentNode.View as IView);

                PopupForm form = currentNode.Tag as PopupForm;

                SetTitle(form, view, null);

                UIContext.Current.ViewContext.Stack.Push(new ViewStackNode(view, ViewDisplayMode.Popup, form, form, null));

                form.RemoveView(currentNode.View);

                int clientWidth = ((Control)view).Width;
                int clientHeight = ((Control)view).Height + PopupForm.ActionBarHeight;

                int deltaWidth = (form.ClientSize.Width - clientWidth) / 2;
                int deltaHeight = (form.ClientSize.Height - clientHeight) / 2;
                form.ClientSize = new System.Drawing.Size(clientWidth, clientHeight);
                Point location = form.DesktopLocation;
                form.SetDesktopLocation(location.X + deltaWidth, location.Y + deltaHeight);;

                ((Control)view).Dock = DockStyle.Fill;
                form.AddView((Control)view);

                ActionNodeCollection actions = UIContext.Current.ViewContext.CreateActionCollection(view);
                view.RegisterAction(actions);

                // layout action
                form.RemoveAllActionButton();
                int left = 10;
                for (int index = 0; index < actions.Count; index++)
                {
                    SimpleButton button = new SimpleButton();
                    button.Height = ActionButtonHeight;
                    button.Name = actions[index].Name;
                    button.Text = actions[index].Caption;
                    button.Visible = actions[index].IsShow;
                    button.Enabled = actions[index].IsEnable;
                    if (actions[index].ClickCallback != null)
                    {
                        button.Click += new EventHandler(actions[index].ClickCallback);
                    }
                    if (actions[index].Image != null)
                    {
                        button.Image = actions[index].Image;
                        button.ImageLocation = ImageLocation.MiddleLeft;
                        button.Width = ActionButtonImageWidth + button.Appearance.CalcTextSizeInt(_mGraphics, actions[index].Caption, ActionButtonMaxWidth).Width;
                    }
                    else
                    {
                        button.Width = ActionButtonNoImageWidth + button.Appearance.CalcTextSizeInt(_mGraphics, actions[index].Caption, ActionButtonMaxWidth).Width;
                    }
                    button.Location = new System.Drawing.Point(left, 5);
                    left += button.Width;
                    left += 10;
                    form.AddActionButton(button);
                }
                form.RelayoutActionButton();

                view.Active(new ViewActiveArgs(""));
            }
        }

        public void SwitchView(IView view)
        {
            ViewStackNode currentNode = UIContext.Current.ViewContext.Stack.Top();
            if (currentNode == null || currentNode.DisplayMode == ViewDisplayMode.Inner)
            {
                SetTitle(view);

                UIContext.Current.ViewContext.Stack.Push(new ViewStackNode(view, ViewDisplayMode.Inner, null, _form, null));

                _ctlViewContainer.HideCurrentView();

                ((Control)view).Dock = DockStyle.Fill;
                _ctlViewContainer.AddView((Control)view);

                ActionNodeCollection actions = UIContext.Current.ViewContext.CreateActionCollection(view);
                view.RegisterAction(actions);
                Utils.ToolbarUtil.ApplyToToolbar(_ctlViewContainer.GetToolbar(), actions);

                view.Active(new ViewActiveArgs(""));
            }
            else
            {
                PopupForm form = currentNode.Tag as PopupForm;
                
                SetTitle(form, view, null);

                UIContext.Current.ViewContext.Stack.Push(new ViewStackNode(view, ViewDisplayMode.Popup, form, form, null));

                form.HideCurrentView();
                //((Control)view).Dock = DockStyle.Fill;
                form.AddView((Control)view);

                int clientWidth = ((Control)view).Width;
                int clientHeight = ((Control)view).Height + PopupForm.ActionBarHeight;

                int deltaWidth = (form.ClientSize.Width - clientWidth) / 2;
                int deltaHeight = (form.ClientSize.Height - clientHeight) / 2;
                form.ClientSize = new System.Drawing.Size(clientWidth, clientHeight);
                Point location = form.DesktopLocation;
                form.SetDesktopLocation(location.X + deltaWidth, location.Y + deltaHeight);

                ActionNodeCollection actions = UIContext.Current.ViewContext.CreateActionCollection(view);
                view.RegisterAction(actions);

                // layout action
                form.RemoveAllActionButton();
                int left = 10;
                for (int index = 0; index < actions.Count; index++)
                {
                    SimpleButton button = new SimpleButton();
                    button.Height = ActionButtonHeight;
                    button.Name = actions[index].Name;
                    button.Text = actions[index].Caption;
                    button.Visible = actions[index].IsShow;
                    button.Enabled = actions[index].IsEnable;
                    if (actions[index].ClickCallback != null)
                    {
                        button.Click += new EventHandler(actions[index].ClickCallback);
                    }
                    if (actions[index].Image != null)
                    {
                        button.Image = actions[index].Image;
                        button.ImageLocation = ImageLocation.MiddleLeft;
                        button.Width = ActionButtonImageWidth + button.Appearance.CalcTextSizeInt(_mGraphics, actions[index].Caption, ActionButtonMaxWidth).Width;
                    }
                    else
                    {
                        button.Width = ActionButtonNoImageWidth + button.Appearance.CalcTextSizeInt(_mGraphics, actions[index].Caption, ActionButtonMaxWidth).Width;
                    }
                    button.Location = new System.Drawing.Point(left, 5);
                    left += button.Width;
                    left += 10;
                    form.AddActionButton(button);
                }
                form.RelayoutActionButton();

                view.Active(new ViewActiveArgs(""));
            }
        }

        public void PopupView(IView view, PopupViewArgs args)
        {
            Control ctlView = (Control)view;

            PopupForm form = new PopupForm();
            SetTitle(form, view, args.Title);
            form.Tag = view;

            int clientWidth = 0;
            int clientHeight = 0;
            if (args.Width != null)
            {
                clientWidth = args.Width.Value;
            }
            else
            {
                clientWidth = ctlView.Width;
            }
            if (args.Height != null)
            {
                clientHeight = args.Height.Value;
            }
            else
            {
                clientHeight = ctlView.Height + PopupForm.ActionBarHeight;
            }
            form.ClientSize = new System.Drawing.Size(clientWidth, clientHeight);

            form.AddView(ctlView);


            ActionNodeCollection actions = UIContext.Current.ViewContext.CreateActionCollection(view);
            view.RegisterAction(actions);

            // layout action
            int left = 10;
            for (int index = 0; index < actions.Count; index++)
            {
                SimpleButton button = new SimpleButton();
                button.Height = ActionButtonHeight;
                button.Name = actions[index].Name;
                button.Text = actions[index].Caption;
                button.Visible = actions[index].IsShow;
                button.Enabled = actions[index].IsEnable;
                if (actions[index].ClickCallback != null)
                {
                    button.Click += new EventHandler(actions[index].ClickCallback);
                }
                if (actions[index].Image != null)
                {
                    button.Image = actions[index].Image;
                    button.ImageLocation = ImageLocation.MiddleLeft;
                    button.Width = ActionButtonImageWidth + button.Appearance.CalcTextSizeInt(_mGraphics, actions[index].Caption, ActionButtonMaxWidth).Width;
                }
                else
                {
                    button.Width = ActionButtonNoImageWidth + button.Appearance.CalcTextSizeInt(_mGraphics, actions[index].Caption, ActionButtonMaxWidth).Width;
                }

                button.Location = new System.Drawing.Point(left, 5);
                left += button.Width;
                left += 10;
                form.AddActionButton(button);
            }
            form.RelayoutActionButton();

            form.FormClosed += new FormClosedEventHandler(OnPopupFormClosed);
            form.Shown += new EventHandler(OnPopupFormShown);
            UIContext.Current.ViewContext.Stack.Push(new ViewStackNode(view, ViewDisplayMode.Popup, form, form, args));
            form.ShowDialog();
        }

        public void CloseView(bool result, object data)
        {
            if (UIContext.Current.ViewContext.Stack.Count == 1)
            {
                return;
            }

            ViewStackNode node = UIContext.Current.ViewContext.Stack.Pop();
            if (node != null)
            {
                // 删除当前view关联的validation
                ValidationManager.Remove(node.View as IView);
                if (node.DisplayMode == ViewDisplayMode.Popup)
                {
                    ViewStackNode prevNode = UIContext.Current.ViewContext.Stack.Top();

                    if (prevNode != null)
                    {
                        if (prevNode.DisplayMode == ViewDisplayMode.Inner)
                        {
                            (node.Tag as PopupForm).IsClosingByXButton = false;
                            if (result)
                            {
                                (node.Tag as Form).DialogResult = DialogResult.OK;
                            }
                            else
                            {
                                (node.Tag as Form).DialogResult = DialogResult.Cancel;
                            }

                            Utils.ToolbarUtil.ApplyToToolbar(_ctlViewContainer.GetToolbar(), UIContext.Current.ViewContext.GetActionCollection(prevNode.View as IView));

                            (prevNode.View as IView).Resume(new ViewResumeArgs(new ViewResumeArgs.ViewClosedArgs(node.View as IView, result, data, node.ActiveArgs)));
                            SetTitle(prevNode.View as IView);
                        }
                        else
                        {
                            if (prevNode.Tag == node.Tag)
                            {
                                // 同一个form一起
                                // 仍然在form里显示view
                                PopupForm form = prevNode.Tag as PopupForm;
                                form.RemoveView(node.View);

                                int clientWidth = ((Control)prevNode.View).Width;
                                int clientHeight = ((Control)prevNode.View).Height + PopupForm.ActionBarHeight;

                                int deltaWidth = (form.ClientSize.Width - clientWidth) / 2;
                                int deltaHeight = (form.ClientSize.Height - clientHeight) / 2;
                                form.ClientSize = new System.Drawing.Size(clientWidth, clientHeight);
                                Point location = form.DesktopLocation;
                                form.SetDesktopLocation(location.X + deltaWidth, location.Y + deltaHeight);

                                ((Control)prevNode.View).Dock = DockStyle.Fill;
                                form.AddView((Control)prevNode.View);

                                // layout action
                                form.RemoveAllActionButton();
                                ActionNodeCollection actions = UIContext.Current.ViewContext.GetActionCollection(prevNode.View as IView);
                                int left = 10;
                                for (int index = 0; index < actions.Count; index++)
                                {
                                    SimpleButton button = new SimpleButton();
                                    button.Height = ActionButtonHeight;
                                    button.Name = actions[index].Name;
                                    button.Text = actions[index].Caption;
                                    button.Visible = actions[index].IsShow;
                                    button.Enabled = actions[index].IsEnable;
                                    if (actions[index].ClickCallback != null)
                                    {
                                        button.Click += new EventHandler(actions[index].ClickCallback);
                                    }

                                    if (actions[index].Image != null)
                                    {
                                        button.Image = actions[index].Image;
                                        button.ImageLocation = ImageLocation.MiddleLeft;
                                        button.Width = ActionButtonImageWidth + button.Appearance.CalcTextSizeInt(_mGraphics, actions[index].Caption, ActionButtonMaxWidth).Width;
                                    }
                                    else
                                    {
                                        button.Width = ActionButtonNoImageWidth + button.Appearance.CalcTextSizeInt(_mGraphics, actions[index].Caption, ActionButtonMaxWidth).Width;
                                    }
                                    button.Location = new System.Drawing.Point(left, 5);
                                    left += button.Width;
                                    left += 10;
                                    form.AddActionButton(button);
                                }
                                form.RelayoutActionButton();

                                if (prevNode.ActiveArgs != null)
                                {
                                    SetTitle(form, prevNode.View as IView, prevNode.ActiveArgs.Title);
                                }
                                else
                                {
                                    SetTitle(form, prevNode.View as IView, null);
                                }
                                (prevNode.View as IView).Resume(new ViewResumeArgs(new ViewResumeArgs.ViewClosedArgs(node.View as IView, result, data, node.ActiveArgs)));
                            }
                            else
                            {
                                // 不再同一个form里，关闭form
                                (node.Tag as PopupForm).IsClosingByXButton = false;
                                if (result)
                                {
                                    (node.Tag as Form).DialogResult = DialogResult.OK;
                                }
                                else
                                {
                                    (node.Tag as Form).DialogResult = DialogResult.Cancel;
                                }
                                (prevNode.View as IView).Resume(new ViewResumeArgs(new ViewResumeArgs.ViewClosedArgs(node.View as IView, result, data, node.ActiveArgs)));
                            }
                        }
                    }
                    else
                    {
                        (node.Tag as PopupForm).IsClosingByXButton = false;
                        if (result)
                        {
                            (node.Tag as Form).DialogResult = DialogResult.OK;
                        }
                        else
                        {
                            (node.Tag as Form).DialogResult = DialogResult.Cancel;
                        }
                    }
                }
                else
                {
                    _ctlViewContainer.RemoveView((Control)node.View);
                    _ctlViewContainer.ShowCurrentView();

                    if (UIContext.Current.ViewContext.Stack.HasAny())
                    {
                        Utils.ToolbarUtil.ApplyToToolbar(_ctlViewContainer.GetToolbar(), UIContext.Current.ViewContext.GetActionCollection(UIContext.Current.ViewContext.Stack.Top().View as IView));

                        SetTitle(UIContext.Current.ViewContext.Stack.Top().View as IView);
                        (UIContext.Current.ViewContext.Stack.Top().View as IView).Resume(new ViewResumeArgs(new ViewResumeArgs.ViewClosedArgs(node.View as IView, result, data, node.ActiveArgs)));
                    }
                }
            }
        }

        private void OnPopupFormShown(object sender, EventArgs e)
        {
            Form form = sender as Form;
            object viewObj = form.Tag;
            IView view = viewObj as IView;
            view.Active(new ViewActiveArgs(""));
        }

        private void OnPopupFormClosed(object sender, FormClosedEventArgs e)
        {
            PopupForm form = sender as PopupForm;
            if (form.IsClosingByXButton && form.DialogResult != DialogResult.OK)
            {
                CloseView(false, null);
            }
        }

        #region mask
        public void ShowMask(IView view, string text)
        {
            ViewStackNode node = UIContext.Current.ViewContext.Stack.Get(view);
            if (node == null)
            {
                return;
            }

            (node.Container as IViewContainer).ShowMask(text);
        }

        public void HideMask(IView view)
        {
            ViewStackNode node = UIContext.Current.ViewContext.Stack.Get(view);
            if (node == null)
            {
                return;
            }

            (node.Container as IViewContainer).HideMask();
        }
        #endregion

        #region message
        /// <summary>
        /// 显示错误消息
        /// </summary>
        /// <param name="message"></param>
        public void ShowError(string message)
        {
            XtraMessageBox.Show(message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }

        /// <summary>
        /// 显示警告消息
        /// </summary>
        /// <param name="message"></param>
        public void ShowWarning(string message)
        {
            XtraMessageBox.Show(message, "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }

        /// <summary>
        /// 显示提示信息
        /// </summary>
        /// <param name="message"></param>
        public void ShowInfo(string message)
        {
            XtraMessageBox.Show(message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }

        /// <summary>
        /// 显示问题窗口
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool ShowQuestion(string message)
        {
            if (XtraMessageBox.Show(message, "询问", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
            {
                return true;
            }
            return false;
        }
        #endregion

        #region action interactive

        /// <summary>
        /// 显示或隐藏动作
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="isShow"></param>
        public void ShowAction(IView view, string name, bool isShow)
        {
            ViewStackNode node = UIContext.Current.ViewContext.Stack.Get(view);
            if (node == null)
            {
                return;
            }

            node.Container.ShowAction(name, isShow);
        }

        /// <summary>
        /// 启用或禁用动作
        /// </summary>
        /// <param name="view"></param>
        /// <param name="name"></param>
        /// <param name="isEnable"></param>
        public void EnableAction(IView view, string name, bool isEnable)
        {
            ViewStackNode node = UIContext.Current.ViewContext.Stack.Get(view);
            if (node == null)
            {
                return;
            }

            node.Container.EnableAction(name, isEnable);
        }

        #endregion
    }
}
